package com.sm2cppa.contract;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.fisco.bcos.sdk.abi.FunctionReturnDecoder;
import org.fisco.bcos.sdk.abi.TypeReference;
import org.fisco.bcos.sdk.abi.datatypes.Address;
import org.fisco.bcos.sdk.abi.datatypes.Event;
import org.fisco.bcos.sdk.abi.datatypes.Function;
import org.fisco.bcos.sdk.abi.datatypes.Type;
import org.fisco.bcos.sdk.abi.datatypes.Utf8String;
import org.fisco.bcos.sdk.abi.datatypes.generated.Bytes32;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple1;
import org.fisco.bcos.sdk.abi.datatypes.generated.tuples.generated.Tuple2;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.contract.Contract;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.eventsub.EventCallback;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.model.callback.TransactionCallback;
import org.fisco.bcos.sdk.transaction.model.exception.ContractException;

@SuppressWarnings("unchecked")
public class MapPkToTx extends Contract {
    public static final String[] BINARY_ARRAY = {"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610794806100606000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806354e63085146100725780637425fcc7146100a35780637934fd961461014d5780638eaa6ac0146101a4578063dd5b64de1461024e575b600080fd5b34801561007e57600080fd5b506100a16004803603810190808035600019169060200190929190505050610305565b005b3480156100af57600080fd5b506100d260048036038101908080356000191690602001909291905050506103cd565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101125780820151818401526020810190506100f7565b50505050905090810190601f16801561013f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561015957600080fd5b5061016261047d565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156101b057600080fd5b506101d360048036038101908080356000191690602001909291905050506104a2565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102135780820151818401526020810190506101f8565b50505050905090810190601f1680156102405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025a57600080fd5b506102c36004803603810190808035600019169060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105a2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561036057600080fd5b6001600082600019166000191681526020019081526020016000206000610387919061067b565b3373ffffffffffffffffffffffffffffffffffffffff167f98c4f0775c8f560c032f85c786c1d36c61cfc85706b2149c1fd4760aa004a8e660405160405180910390a250565b60016020528060005260406000206000915090508054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104755780601f1061044a57610100808354040283529160200191610475565b820191906000526020600020905b81548152906001019060200180831161045857829003601f168201915b505050505081565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60603373ffffffffffffffffffffffffffffffffffffffff167fc065cfc6edc7c4115dd4ed3a8d2bb25d8700cd0c45b70628feb271c89ef0b89f60405160405180910390a26001600083600019166000191681526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105965780601f1061056b57610100808354040283529160200191610596565b820191906000526020600020905b81548152906001019060200180831161057957829003601f168201915b50505050509050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156105ff57600080fd5b81600160008560001916600019168152602001908152602001600020908051906020019061062e9291906106c3565b503373ffffffffffffffffffffffffffffffffffffffff167fa2671505b0099003d5ed5bc8b0fb328161153bfba1b8014cd469b816cbd37c1660405160405180910390a233905092915050565b50805460018160011615610100020316600290046000825580601f106106a157506106c0565b601f0160209004906000526020600020908101906106bf9190610743565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061070457805160ff1916838001178555610732565b82800160010185558215610732579182015b82811115610731578251825591602001919060010190610716565b5b50905061073f9190610743565b5090565b61076591905b80821115610761576000816000905550600101610749565b5090565b905600a165627a7a72305820e51bed8b075959ef35a1cf86b190efe531485789ea8d7e9fed2b2fd4f376cede0029"};

    public static final String BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", BINARY_ARRAY);

    public static final String[] SM_BINARY_ARRAY = {"608060405234801561001057600080fd5b50336000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610794806100606000396000f30060806040526004361061006d576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680631085b3f21461007257806329f7b1fb146100c9578063301d1b2f146100fa57806388805210146101a4578063de8705a61461024e575b600080fd5b34801561007e57600080fd5b50610087610305565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156100d557600080fd5b506100f8600480360381019080803560001916906020019092919050505061032a565b005b34801561010657600080fd5b5061012960048036038101908080356000191690602001909291905050506103f2565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561016957808201518184015260208101905061014e565b50505050905090810190601f1680156101965780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156101b057600080fd5b506101d360048036038101908080356000191690602001909291905050506104a2565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156102135780820151818401526020810190506101f8565b50505050905090810190601f1680156102405780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025a57600080fd5b506102c36004803603810190808035600019169060200190929190803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091929192905050506105a2565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614151561038557600080fd5b60016000826000191660001916815260200190815260200160002060006103ac919061067b565b3373ffffffffffffffffffffffffffffffffffffffff167fb385a67dca15a88a7ecd5f830e8cbaa5d40924c0ac4dd60ca6a83ec4c67b6e3860405160405180910390a250565b60016020528060005260406000206000915090508054600181600116156101000203166002900480601f01602080910402602001604051908101604052809291908181526020018280546001816001161561010002031660029004801561049a5780601f1061046f5761010080835404028352916020019161049a565b820191906000526020600020905b81548152906001019060200180831161047d57829003601f168201915b505050505081565b60603373ffffffffffffffffffffffffffffffffffffffff167fc5c6bb1591800c60583d8ccb8d4e256e1031b6929effd4305cf31e6f29321f1060405160405180910390a26001600083600019166000191681526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156105965780601f1061056b57610100808354040283529160200191610596565b820191906000526020600020905b81548152906001019060200180831161057957829003601f168201915b50505050509050919050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415156105ff57600080fd5b81600160008560001916600019168152602001908152602001600020908051906020019061062e9291906106c3565b503373ffffffffffffffffffffffffffffffffffffffff167f0d25a934afb440a6fe4a8ba20ecaea0b9e75d131ab271e5f586bda6e5835514f60405160405180910390a233905092915050565b50805460018160011615610100020316600290046000825580601f106106a157506106c0565b601f0160209004906000526020600020908101906106bf9190610743565b5b50565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061070457805160ff1916838001178555610732565b82800160010185558215610732579182015b82811115610731578251825591602001919060010190610716565b5b50905061073f9190610743565b5090565b61076591905b80821115610761576000816000905550600101610749565b5090565b905600a165627a7a7230582084415ea049d8d3d9b8364a9228415f98ee63f9486142154e5869fea7334d385e0029"};

    public static final String SM_BINARY = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", SM_BINARY_ARRAY);

    public static final String[] ABI_ARRAY = {"[{\"constant\":false,\"inputs\":[{\"name\":\"target\",\"type\":\"bytes32\"}],\"name\":\"deletetx\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"PK2TX\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"ca\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"pkhash\",\"type\":\"bytes32\"}],\"name\":\"get\",\"outputs\":[{\"name\":\"txid\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"pkhash\",\"type\":\"bytes32\"},{\"name\":\"txid\",\"type\":\"string\"}],\"name\":\"update\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"requester\",\"type\":\"address\"}],\"name\":\"_update\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"requester\",\"type\":\"address\"}],\"name\":\"_get\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"requester\",\"type\":\"address\"}],\"name\":\"_deletetx\",\"type\":\"event\"}]"};

    public static final String ABI = org.fisco.bcos.sdk.utils.StringUtils.joinAll("", ABI_ARRAY);

    public static final String FUNC_DELETETX = "deletetx";

    public static final String FUNC_PK2TX = "PK2TX";

    public static final String FUNC_CA = "ca";

    public static final String FUNC_GET = "get";

    public static final String FUNC_UPDATE = "update";

    public static final Event _UPDATE_EVENT = new Event("_update", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}));
    ;

    public static final Event _GET_EVENT = new Event("_get", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}));
    ;

    public static final Event _DELETETX_EVENT = new Event("_deletetx", 
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}));
    ;

    protected MapPkToTx(String contractAddress, Client client, CryptoKeyPair credential) {
        super(getBinary(client.getCryptoSuite()), contractAddress, client, credential);
    }

    public static String getBinary(CryptoSuite cryptoSuite) {
        return (cryptoSuite.getCryptoTypeConfig() == CryptoType.ECDSA_TYPE ? BINARY : SM_BINARY);
    }

    public TransactionReceipt deletetx(byte[] target) {
        final Function function = new Function(
                FUNC_DELETETX, 
                Arrays.<Type>asList(new Bytes32(target)),
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] deletetx(byte[] target, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_DELETETX, 
                Arrays.<Type>asList(new Bytes32(target)),
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForDeletetx(byte[] target) {
        final Function function = new Function(
                FUNC_DELETETX, 
                Arrays.<Type>asList(new Bytes32(target)),
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple1<byte[]> getDeletetxInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_DELETETX, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<byte[]>(

                (byte[]) results.get(0).getValue()
                );
    }

    public String PK2TX(byte[] param0) throws ContractException {
        final Function function = new Function(FUNC_PK2TX, 
                Arrays.<Type>asList(new Bytes32(param0)),
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public String ca() throws ContractException {
        final Function function = new Function(FUNC_CA, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public String get(byte[] pkhash) throws ContractException {
        final Function function = new Function(FUNC_GET, 
                Arrays.<Type>asList(new Bytes32(pkhash)),
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        return executeCallWithSingleValueReturn(function, String.class);
    }

    public TransactionReceipt update(byte[] pkhash, String txid) {
        final Function function = new Function(
                FUNC_UPDATE, 
                Arrays.<Type>asList(new Bytes32(pkhash),
                new Utf8String(txid)),
                Collections.<TypeReference<?>>emptyList());
        return executeTransaction(function);
    }

    public byte[] update(byte[] pkhash, String txid, TransactionCallback callback) {
        final Function function = new Function(
                FUNC_UPDATE, 
                Arrays.<Type>asList(new Bytes32(pkhash),
                new Utf8String(txid)),
                Collections.<TypeReference<?>>emptyList());
        return asyncExecuteTransaction(function, callback);
    }

    public String getSignedTransactionForUpdate(byte[] pkhash, String txid) {
        final Function function = new Function(
                FUNC_UPDATE, 
                Arrays.<Type>asList(new Bytes32(pkhash),
                new Utf8String(txid)),
                Collections.<TypeReference<?>>emptyList());
        return createSignedTransaction(function);
    }

    public Tuple2<byte[], String> getUpdateInput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getInput().substring(10);
        final Function function = new Function(FUNC_UPDATE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Bytes32>() {}, new TypeReference<Utf8String>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple2<byte[], String>(

                (byte[]) results.get(0).getValue(), 
                (String) results.get(1).getValue()
                );
    }

    public Tuple1<String> getUpdateOutput(TransactionReceipt transactionReceipt) {
        String data = transactionReceipt.getOutput();
        final Function function = new Function(FUNC_UPDATE, 
                Arrays.<Type>asList(), 
                Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));
        List<Type> results = FunctionReturnDecoder.decode(data, function.getOutputParameters());
        return new Tuple1<String>(

                (String) results.get(0).getValue()
                );
    }

    public List<_updateEventResponse> get_updateEvents(TransactionReceipt transactionReceipt) {
        List<EventValuesWithLog> valueList = extractEventParametersWithLog(_UPDATE_EVENT, transactionReceipt);
        ArrayList<_updateEventResponse> responses = new ArrayList<_updateEventResponse>(valueList.size());
        for (EventValuesWithLog eventValues : valueList) {
            _updateEventResponse typedResponse = new _updateEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.requester = (String) eventValues.getIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribe_updateEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(_UPDATE_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribe_updateEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(_UPDATE_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<_getEventResponse> get_getEvents(TransactionReceipt transactionReceipt) {
        List<EventValuesWithLog> valueList = extractEventParametersWithLog(_GET_EVENT, transactionReceipt);
        ArrayList<_getEventResponse> responses = new ArrayList<_getEventResponse>(valueList.size());
        for (EventValuesWithLog eventValues : valueList) {
            _getEventResponse typedResponse = new _getEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.requester = (String) eventValues.getIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribe_getEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(_GET_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribe_getEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(_GET_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public List<_deletetxEventResponse> get_deletetxEvents(TransactionReceipt transactionReceipt) {
        List<EventValuesWithLog> valueList = extractEventParametersWithLog(_DELETETX_EVENT, transactionReceipt);
        ArrayList<_deletetxEventResponse> responses = new ArrayList<_deletetxEventResponse>(valueList.size());
        for (EventValuesWithLog eventValues : valueList) {
            _deletetxEventResponse typedResponse = new _deletetxEventResponse();
            typedResponse.log = eventValues.getLog();
            typedResponse.requester = (String) eventValues.getIndexedValues().get(0).getValue();
            responses.add(typedResponse);
        }
        return responses;
    }

    public void subscribe_deletetxEvent(String fromBlock, String toBlock, List<String> otherTopics, EventCallback callback) {
        String topic0 = eventEncoder.encode(_DELETETX_EVENT);
        subscribeEvent(ABI,BINARY,topic0,fromBlock,toBlock,otherTopics,callback);
    }

    public void subscribe_deletetxEvent(EventCallback callback) {
        String topic0 = eventEncoder.encode(_DELETETX_EVENT);
        subscribeEvent(ABI,BINARY,topic0,callback);
    }

    public static MapPkToTx load(String contractAddress, Client client, CryptoKeyPair credential) {
        return new MapPkToTx(contractAddress, client, credential);
    }

    public static MapPkToTx deploy(Client client, CryptoKeyPair credential) throws ContractException {
        return deploy(MapPkToTx.class, client, credential, getBinary(client.getCryptoSuite()), "");
    }

    public static class _updateEventResponse {
        public TransactionReceipt.Logs log;

        public String requester;
    }

    public static class _getEventResponse {
        public TransactionReceipt.Logs log;

        public String requester;
    }

    public static class _deletetxEventResponse {
        public TransactionReceipt.Logs log;

        public String requester;
    }
}
